mod models;
mod operations;

use axum::{
    Router,
    routing::post,
    routing::get,
    routing::delete,
    routing::patch,
    extract::{Json},
    http::StatusCode,
    response::{IntoResponse, Response},
};
use tower_http::services::ServeDir;
use tower_http::cors::{CorsLayer, Any};
use std::net::SocketAddr;
use sqlx::{mysql::MySqlPoolOptions};
use dotenvy::dotenv;
use std::env;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    dotenv().ok();
    // 从环境变量获取配置
    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set (DATABASE_URL 必须在同级目录下的名为.env的文件中设置，eg: DATABASE_URL=mysql://root:1234@localhost:3306/dbhomework)");
    let max_connections = env::var("DATABASE_MAX_CONNECTIONS")
        .unwrap_or_else(|_| "5".to_string())
        .parse::<u32>()
        .expect("DATABASE_MAX_CONNECTIONS must be a number (DATABASE_MAX_CONNECTIONS 必须在同级目录下的名为.env的文件中设置，必须是一个数字，eg：DATABASE_MAX_CONNECTIONS=5)");
    let server_port = env::var("SERVER_PORT")
        .unwrap_or_else(|_| "3001".to_string())
        .parse::<u16>()
        .expect("SERVER_PORT must be a number (SERVER_PORT 必须在同级目录下的名为.env的文件中设置，必须是一个数字，eg: SERVER_PORT=3001)");
    println!("正在连接数据库...");
    
    let pool = MySqlPoolOptions::new()
        .max_connections(max_connections)
        .connect(&database_url)
        .await?;

    println!("数据库连接成功！");

    // 构建应用路由
    let app = Router::new()
        .route("/api/user_login", post(crate::operations::user_operations::login))
        .route("/api/user_register", post(crate::operations::user_operations::create))
        .route("/api/user_getall", post(crate::operations::user_operations::getall))

        .route("/api/commodity_getall", get(crate::operations::commodity_operations::getall))
        .route("/api/commodity_create", post(crate::operations::commodity_operations::create))
        .route("/api/commodity_delete", delete(crate::operations::commodity_operations::delete))

        .route("/api/handover_getall", get(crate::operations::handover_operations::getall))
        .route("/api/handover_create", post(crate::operations::handover_operations::create))
        .route("/api/handover_delete", delete(not_implemented))

        .route("/api/member_getall", get(crate::operations::member_operations::getall))
        .route("/api/member_create", post(crate::operations::member_operations::create))
        .route("/api/member_delete", delete(crate::operations::member_operations::delete))

        .route("/api/plan_getall", get(crate::operations::plan_operations::getall))
        .route("/api/plan_create", post(crate::operations::plan_operations::create))
        .route("/api/plan_delete", delete(crate::operations::plan_operations::delete))

        .route("/api/sale_getall", get(crate::operations::sale_operations::getall))
        .route("/api/sale_create", post(crate::operations::sale_operations::create))
        .route("/api/sale_delete", delete(crate::operations::sale_operations::delete))

        .route("/api/sale_statistics_getall", get(crate::operations::sale_statistics_operations::getall))
        .route("/api/sale_statistics_create", post(crate::operations::sale_statistics_operations::create))
        .route("/api/sale_statistics_delete", delete(crate::operations::sale_statistics_operations::delete))

        .route("/api/store_getall", get(crate::operations::store_operations::getall))
        .route("/api/store_create", post(crate::operations::store_operations::create))
        .route("/api/store_delete", delete(crate::operations::store_operations::delete))

        .route("/api/stored_getall", get(crate::operations::stored_operations::getall))
        .route("/api/stored_create", post(crate::operations::stored_operations::create))
        .route("/api/stored_delete", delete(crate::operations::stored_operations::delete))
        .route("/api/stored_update", patch(crate::operations::stored_operations::update))

        .fallback_service(ServeDir::new("static"))
        .layer(
            CorsLayer::new()
                .allow_origin(Any)
                .allow_methods(Any)
                .allow_headers(Any)
        )
        .with_state(pool);

    // 运行服务器
    let addr = SocketAddr::from(([0, 0, 0, 0], server_port));
    println!("服务器运行在 http://{}", addr);
    
    let listener = tokio::net::TcpListener::bind(addr).await?;
    axum::serve(listener, app).await?;

    Ok(())
}

async fn not_implemented() -> Response {
    (
        StatusCode::NOT_IMPLEMENTED,
        Json(serde_json::json!({
            "error": "接口尚未实现"
        }))
    ).into_response()
}